package com.base.dynamicprograming;

import java.util.ArrayList;
import java.util.List;

/**
 * 120. 三角形最小路径和
 *  给定一个三角形 triangle ，找出自顶向下的最小路径和。
 *
 *  每一步只能移动到下一行中相邻的结点上。相邻的结点 在这里指的是 下标 与 上一层结点下标 相同或者等于 上一层结点下标 + 1 的两个结点。也就是说，如果正位于当前行的下标 i ，那么下一步可以移动到下一行的下标 i 或 i + 1
 *
 *  来源：力扣（LeetCode）
 *  链接：https://leetcode-cn.com/problems/triangle
 *  著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 * @author leon
 * @date 2021年12月13日 12:43
 */
public class MinimumTotal {
    public int minimumTotal(List<List<Integer>> triangle) {
        int n = triangle.size();
        int[] dp = new int[n];
        dp[0] = triangle.get(0).get(0);
        for (int i = 1; i < n; i++) {
            // 当前层的最后一个状态
            dp[i] = dp[i-1] + triangle.get(i).get(i);
            for (int j = i-1; j > 0; j--) {
                dp[j] = Math.min(dp[j],dp[j-1]) + triangle.get(i).get(j);
            }
            // 当前层的第一个状态
            dp[0] = dp[0] + triangle.get(i).get(0);
        }
        int res = dp[0];
        for (int i = 1; i < n; i++) {
            res = Math.min(res,dp[i]);
        }
        return res;
    }


    //leetcode 优化
    public int minimumTotal1(List<List<Integer>> triangle) {
        // 三角形的层数
        int n = triangle.size();
        // 用数组存放状态
        int[] f = new int[n];
        // 第0层的状态
        f[0] = triangle.get(0).get(0);
        for (int i = 1; i < n; ++i) {
            f[i] = f[i - 1] + triangle.get(i).get(i);
            for (int j = i - 1; j > 0; --j) {
                f[j] = Math.min(f[j - 1], f[j]) + triangle.get(i).get(j);
            }
            f[0] += triangle.get(i).get(0);
        }
        int minTotal = f[0];
        for (int i = 1; i < n; ++i) {
            minTotal = Math.min(minTotal, f[i]);
        }
        return minTotal;
    }
}
